package com.ship.dispatch.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONArray;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.google.gson.Gson;
import com.google.gson.JsonObject;
import com.ship.common.business.service.impl.BaseServiceImpl;
import com.ship.common.core.base.Page;
import com.ship.common.core.domain.R;
import com.ship.common.core.exception.BusException;
import com.ship.common.core.web.domain.BaseResultCode;
import com.ship.common.core.web.domain.JsonResult;
import com.ship.common.security.utils.SecurityUtils;
import com.ship.dispatch.bean.SpOverhaul;
import com.ship.dispatch.bean.SpQualifications;
import com.ship.dispatch.bean.fob.SpFobFileRecord;
import com.ship.dispatch.bo.SpQualificationsBo;
import com.ship.dispatch.mapper.SpQualificationsMapper;
import com.ship.dispatch.service.SpQualificationsService;
import com.ship.dispatch.service.fob.SpFobFileRecordService;
import com.ship.dispatch.vo.SpOverhaulVo;
import com.ship.system.api.RemoteFileService;
import com.ship.system.api.domain.SysFile;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.*;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLDecoder;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.text.SimpleDateFormat;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

@Service
public class SpQualificationsServiceImpl extends BaseServiceImpl<SpQualificationsMapper, SpQualifications> implements SpQualificationsService {
    @Autowired
    SpQualificationsMapper spQualificationsMapper;

    @Autowired
    SpFobFileRecordService spFobFileRecordService;

    @Value("${file_server.host}")
    private String fileServerHost;

    @Autowired
    private RemoteFileService remoteFileService;

    @Override
    public JsonResult schemeAdd(SpQualifications spQualifications) {
        String imo = spQualificationsMapper.getImoByName(spQualifications.getNameOfVessel());
        spQualifications.setImo(imo);
        spQualifications.setDelApply(0);
        Date expirationTime = spQualifications.getExpirationTime();
       if (spQualifications.getSignDate() !=null) {
           Calendar calendar = Calendar.getInstance();
           calendar.setTime(spQualifications.getSignDate()); // 设置calendar为signDate的日期
           calendar.add(Calendar.MONTH, spQualifications.getExpirationDate()); // 将monthsToAdd添加到calendar的月份中
           spQualifications.setExpirationTime(calendar.getTime());
       }
        if(spQualifications.getExpirationTime()!=null){
            spQualifications.setExpirationTime(expirationTime);
        }

        super.save(spQualifications);

        Long id = Long.valueOf(spQualifications.getId());
        SpFobFileRecord spFobFileRecord = new SpFobFileRecord();
        spFobFileRecord.setOverhaulId(id);

        for (String fileId : spQualifications.getFileIds()) {
            spFobFileRecord.setId(Long.valueOf(fileId));
            spFobFileRecordService.updateById(spFobFileRecord);
        }
        return JsonResult.success(spQualifications);
    }

    @Override
    public JsonResult getListInfo(SpQualificationsBo spQualificationsBo) {
//        List<SpQualifications> result;
//        Page<SpQualifications> resultPage = new Page<>();;
//        if (!isEmptyList(spQualificationsBo.getImo()) || !isEmptyList(spQualificationsBo.getNameOfVessel()) || !isEmptyList(spQualificationsBo.getCertName()) || !isEmptyList(spQualificationsBo.getSignAgency())) {
//            // 如果 imo 或者 nameOfVessel 不为空，执行模糊查询
//            QueryWrapper<SpQualifications> queryWrapper = new QueryWrapper<>();
//            if (!isEmptyList(spQualificationsBo.getImo())) {
//                for (String imo : spQualificationsBo.getImo()) {
//                    queryWrapper.or(qw -> qw.like("imo", "%" + imo + "%").eq("del_apply", 0));
//                }
//            }
//            if (!isEmptyList(spQualificationsBo.getNameOfVessel())) {
//                for (String shipName : spQualificationsBo.getNameOfVessel()) {
//                    queryWrapper.or(qw -> qw.like("name_of_vessel", "%" + shipName + "%").eq("del_apply", 0));
//                }
//            }
//            if (!isEmptyList(spQualificationsBo.getCertName())) {
//                for (String certName : spQualificationsBo.getCertName()) {
//                    queryWrapper.or(qw -> qw.like("cert_name", "%" + certName + "%").eq("del_apply", 0));
//                }
//            }
//            if (!isEmptyList(spQualificationsBo.getSignAgency())) {
//                for (String signAgency : spQualificationsBo.getSignAgency()) {
//                    queryWrapper.or(qw -> qw.like("sign_agency", "%" + signAgency + "%").eq("del_apply", 0));
//                }
//            }
//            queryWrapper.orderByDesc("create_date");
//
//            PageHelper.startPage(spQualificationsBo.getPageNum(), spQualificationsBo.getPageSize());
//            result = spQualificationsMapper.selectList(queryWrapper);
//        } else {
////           如果 imo 和 nameOfVessel 均为空，查询全部结果
//            PageHelper.startPage(spQualificationsBo.getPageNum(), spQualificationsBo.getPageSize());
//            result = spQualificationsMapper.getInfo();
//        }
//        int totalItems = result.size();
//        resultPage.setList(result);
//        resultPage.setPageNum(spQualificationsBo.getPageNum());
//        resultPage.setPageSize(spQualificationsBo.getPageSize());
//        resultPage.setTotal(totalItems);
        PageHelper.startPage(spQualificationsBo.getPageNum(), spQualificationsBo.getPageSize());
        List<SpQualifications> result =  spQualificationsMapper.queryQualificationList(spQualificationsBo);
        PageInfo<SpQualifications> pageInfo = new PageInfo<>(result);
        return JsonResult.success(pageInfo);
    }

    @Override
    public JsonResult<Object> getshipList() {
        List<String> list = spQualificationsMapper.getShipList()
                .stream()
                .filter(ship -> !ship.startsWith("虚拟船"))
                .collect(Collectors.toList());
        return JsonResult.success(list);
    }

    @Override
    public void delApply(Long id) {
        SpQualifications spQualifications = super.getById(id);
        if (spQualifications == null) {
            throw new BusException("删除申请失败!该记录不存在", BaseResultCode.GENERAL_ERROR);
        }
        spQualifications.setDelApply(1);
        super.updateById(spQualifications);
    }

    @Override
    public String export(SpOverhaulVo spOverhaulVo) throws IOException {
        List<String> ids = spOverhaulVo.getIds();
        List<SpQualifications> spQualifications;
        if (ids == null || ids.isEmpty()) {
            spQualifications = spQualificationsMapper.getInfo();
        } else {
            spQualifications = spQualificationsMapper.getInFOById(ids);
        }
        Date currentTime = new Date();
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss");
        String dateString = dateFormat.format(currentTime);
        String folderName = "船舶资质-" + dateString;
        String zipFileName = folderName + ".zip";

        try (FileOutputStream fos = new FileOutputStream(zipFileName);
             ZipOutputStream zos = new ZipOutputStream(fos)) {
            if (spOverhaulVo.getType()) {
                // 创建目录
                File folder = new File(folderName);
                if (!folder.exists()) {
                    folder.mkdirs();
                }
                for (SpQualifications spQualifications1 : spQualifications) {
                    String nameOfVessel = spQualifications1.getNameOfVessel();
                    JSONArray jsonArray = new JSONArray(spQualificationsMapper.getFileById(spQualifications1.getId()));
                    String fileUrl = jsonArray.toString();
                    if (fileUrl != null && !fileUrl.isEmpty() && !fileUrl.equals("[]")) {
                        fileUrl = fileUrl.replaceAll("\\[|\\]", "");
                        String[] urls = fileUrl.split(",");
                        for (String url : urls) {
                            url = url.trim().replaceAll("^\"|\"$", "");
                            if (!url.matches("^\\w+://.*$")) {
                                url = "http://" + url;
                            }
                            downloadFile(url, folderName + "/" + nameOfVessel);
                        }
                    }
                }
                exportToExcel(spQualifications, folderName + "/" + folderName + ".xlsx");
                zipDirectory(new File(folderName), zos, folderName + "/");
            } else {
                exportToExcel(spQualifications, folderName + ".xlsx");
                zipFileName = folderName + ".xlsx";
//                zipFile(folderName + ".xlsx");
            }

        }
        //文件地址
        File file = new File(zipFileName);
//        //声明参数集合
//        HashMap<String, Object> paramMap = new HashMap<>();
//        //文件
//        paramMap.put("file", file);
//        //输出
//        paramMap.put("output","json");
//        //自定义路径
//        paramMap.put("path","image");
//        //场景
//        paramMap.put("scene","image");
//
//        paramMap.put("filename",zipFileName);
//
//        String result= HttpUtil.post(fileServerHost+"/group1/upload", paramMap);
        FileInputStream input = new FileInputStream(file);
        MultipartFile multipartFile = new MockMultipartFile("file", file.getName(), "application/octet-stream", input);
        R<SysFile> result1 = remoteFileService.upload(multipartFile);
        if(result1.getCode() != R.SUCCESS){
            throw new BusException("文件服务器连接失败", BaseResultCode.GENERAL_ERROR);
        }
        String url = result1.getData().getHttpsUrl();

        File zipFile = new File(zipFileName);
        if (spOverhaulVo.getType()) {

            if (zipFile.exists()) {
                deleteFolder(folderName);
            }else {
                File excel = new File(folderName + ".xlsx");
                if (excel.exists()) {
                    excel.delete();
                }
            }
        }else {
            File zipFile2 = new File(folderName + ".zip");
            zipFile2.delete();
        }
        if (zipFile.exists()) {
            zipFile.delete();
        }
//        Gson gson = new Gson();
//        JsonObject jsonObject = gson.fromJson(result, JsonObject.class);
//        // 获取"url"字段的值
//        String url = jsonObject.get("url").getAsString();
        return url;
    }

    @Override
    public SpQualifications detail(Long id) {
        SpQualifications spQualifications = spQualificationsMapper.getById(String.valueOf(id));
        List<Map<String, String>> list = spQualificationsMapper.getFileIdById(id);

        List<Map<String, String>> updatedList = new ArrayList<>();

        for (Map<String, String> map : list) {
            Map<String, String> updatedMap = new HashMap<>();

            // 复制原有的值
            updatedMap.putAll(map);

            // 转换overhaulId为String类型
            String overhaulIdStr = String.valueOf(map.get("fileId"));
            updatedMap.put("fileId", overhaulIdStr);

            // 提取文件名并添加到map中
            String url = map.get("url");
            if (url != null) {
                int lastSlashIndex = url.lastIndexOf("/");
                if (lastSlashIndex != -1 && lastSlashIndex + 1 < url.length()) {
                    String encodedFileName = url.substring(lastSlashIndex + 1);
                    String decodedFileName = null;
                    try {
                        decodedFileName = URLDecoder.decode(encodedFileName, "UTF-8");
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                    updatedMap.put("fileName", decodedFileName);
                }
            }

            updatedList.add(updatedMap);
        }

        spQualifications.setFile(updatedList);

//        Map<String,Object> result = new HashMap<>();
//        result.put("id",spQualifications.getId());
//        result.put("nameOfVessel",spQualifications.getNameOfVessel());
//        result.put("IMO",spQualifications.getImo());
//        result.put("certName",spQualifications.getCertName());
//        result.put("signDate",spQualifications.getSignDate());
//        result.put("signAgency",spQualifications.getSignAgency());
//        result.put("expirationDate",spQualifications.getExpirationDate());
//        result.put("expirationTime",spQualifications.getExpirationTime());
//        result.put("remarks",spQualifications.getRemarks());
//        result.put("file",spQualifications.getFile());

        return spQualifications;
    }

    @Override
    public void updateCon(SpQualifications spQualifications) {
        SpQualifications spQualifications1 = super.getById(spQualifications.getId());
        SpQualifications spQualifications2 = spQualifications;
        if (spQualifications1.getImo() != null && spQualifications.getImo() != null) {
            if (!spQualifications.getImo().equals(spQualifications1.getImo())) {
                spQualifications2.setNameOfVessel(spQualificationsMapper.getNameByImo(spQualifications.getImo()));
            }
        }
        if (spQualifications1.getNameOfVessel()!=null && spQualifications.getNameOfVessel()!=null){
            if (!spQualifications.getNameOfVessel().equals(spQualifications1.getNameOfVessel())){
                spQualifications2.setImo(spQualificationsMapper.getImoByName(spQualifications.getNameOfVessel()));
            }
        }
        if (spQualifications.getSignDate() !=null) {
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(spQualifications.getSignDate()); // 设置calendar为signDate的日期
            calendar.add(Calendar.MONTH, spQualifications.getExpirationDate()); // 将monthsToAdd添加到calendar的月份中
            spQualifications.setExpirationTime(calendar.getTime());
        }else {
            spQualificationsMapper.deleteSignDate(spQualifications.getId());
        }
        spQualifications.setCreateBy(SecurityUtils.getUsername());
        super.updateById(spQualifications);
        String QuaId = String.valueOf(spQualifications.getId());
        List<String> ids = spQualifications.getFileIds();
        if(StringUtils.isNotBlank(QuaId)){
            if (CollectionUtil.isNotEmpty(ids)) {
                spFobFileRecordService.getBaseMapper().delete(new LambdaQueryWrapper<SpFobFileRecord>()
                        .eq(SpFobFileRecord::getOverhaulId, QuaId)
                        .eq(SpFobFileRecord::getFileType, "船舶资质")
                        .notIn(SpFobFileRecord::getId, ids));
                List<SpFobFileRecord> fileList = spFobFileRecordService.getBaseMapper().selectList(new LambdaQueryWrapper<SpFobFileRecord>()
                        .eq(SpFobFileRecord::getOverhaulId, QuaId)
                        .eq(SpFobFileRecord::getFileType, "船舶资质"));
                if (CollectionUtil.isNotEmpty(fileList)) {
                    List<Long> fileIdList = fileList.stream().map(SpFobFileRecord::getId).collect(Collectors.toList());
                    ids.forEach(item -> {
                        if (!fileIdList.contains(Long.valueOf(item))) {
                            spFobFileRecordService.getBaseMapper().update(null, new LambdaUpdateWrapper<SpFobFileRecord>()
                                    .eq(SpFobFileRecord::getId, item)
                                    .set(SpFobFileRecord::getOverhaulId, QuaId));
                        }
                    });
                } else {
                    ids.forEach(item -> {
                        spFobFileRecordService.getBaseMapper().update(null, new LambdaUpdateWrapper<SpFobFileRecord>()
                                .eq(SpFobFileRecord::getId, item)
                                .set(SpFobFileRecord::getOverhaulId, QuaId));
                    });
                }
            }else {
                spFobFileRecordService.getBaseMapper().delete(new LambdaQueryWrapper<SpFobFileRecord>()
                        .eq(SpFobFileRecord::getOverhaulId, QuaId)
                        .eq(SpFobFileRecord::getFileType, "船舶资质"));
            }
        }

//        for (String id : ids) {
//            spQualificationsMapper.upDateFileId(id,QuaId);
//        }
    }

    @Override
    public List<Map<String, String>> shipAndImo() {
        List<Map<String, String>> stringStringMap = spQualificationsMapper.getShipAndImo();
        return stringStringMap;}

    @Override
    public List<Map<String, String>> nowShipAndImo() {
        List<Map<String, String>> stringStringMap = spQualificationsMapper.getNowShipAndImo();
        return stringStringMap;
    }

    private boolean isEmptyList(List<?> list) {
        return list == null || list.isEmpty();
    }

    public void downloadFile(String fileUrl, String destinationFolder) throws IOException {
//        URL url = new URL(fileUrl);
//        URLConnection conn = url.openConnection();
//        InputStream inputStream = conn.getInputStream();

        String CsoldPart = "http://10.75.34.224:9300/statics";
        String ZsoldPart = "http://10.75.33.149:9300/statics";
        String CsPart = "https://lngshippingcs.cgp.cnooc/api/file/statics";
        String ZsPart = "https://lngshipping.cgp.cnooc/api/file/statics";

        String newUrl = "";
        if (fileUrl.contains("https://lngshipping.cgp.cnooc")) {
            newUrl = fileUrl.replace(ZsPart, ZsoldPart);
        }else if (fileUrl.contains("https://lngshippingcs.cgp.cnooc")){
            newUrl = fileUrl.replace(CsPart, CsoldPart);
        }else {
            newUrl = fileUrl;
        }

        URL outUrl = new URL(newUrl);
        URLConnection conn = outUrl.openConnection();
        InputStream inputStream = conn.getInputStream();


        Path folderPath = Paths.get(destinationFolder);
        if (!Files.exists(folderPath)) {
            Files.createDirectories(folderPath);
        }

        String fileName = fileUrl.substring(fileUrl.lastIndexOf("/") + 1);
        String filePath = destinationFolder + "/" + fileName;

        try (FileOutputStream outputStream = new FileOutputStream(filePath)) {
            byte[] buffer = new byte[1024];
            int bytesRead;
            while ((bytesRead = inputStream.read(buffer)) != -1) {
                outputStream.write(buffer, 0, bytesRead);
            }
        }
    }

    public static void exportToExcel(List<SpQualifications> spOverhaulVos, String filePath) throws IOException {
        Workbook workbook = new XSSFWorkbook();
        Sheet sheet = workbook.createSheet("SpQualifications Data");

        Row headerRow = sheet.createRow(0);
        String[] headers = {"船舶名称", "IMO", "证书名称", "签发日期","签发机构","有效期","到期日期", "备注", "操作人", "操作时间"};
        for (int i = 0; i < headers.length; i++) {
            Cell cell = headerRow.createCell(i);
            cell.setCellValue(headers[i]);
        }

        int rowNum = 1;
        DateTimeFormatter formatter1 = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        DateTimeFormatter formatter2 = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        for (SpQualifications spQualifications : spOverhaulVos) {
            Row row = sheet.createRow(rowNum++);
            String formattedDate1 = null;
            String formattedDate2 = null;
            String expirationDateStr = null;
            Integer expirationDate = 0;
            if (spQualifications.getSignDate() != null) {
                formattedDate1 = spQualifications.getSignDate().toInstant()
                        .atZone(ZoneId.systemDefault())
                        .toLocalDateTime()
                        .format(formatter1);
            }
            if (spQualifications.getExpirationTime() != null) {
                formattedDate2 = spQualifications.getExpirationTime().toInstant()
                        .atZone(ZoneId.systemDefault())
                        .toLocalDateTime()
                        .format(formatter1);
            }
            if (spQualifications.getExpirationDate() != null) {
                expirationDate = spQualifications.getExpirationDate();
                expirationDateStr = expirationDate + "个月";
            }
            row.createCell(0).setCellValue(spQualifications.getNameOfVessel());
            row.createCell(1).setCellValue(spQualifications.getImo());
            row.createCell(2).setCellValue(spQualifications.getCertName());
            row.createCell(3).setCellValue(formattedDate1);
            row.createCell(4).setCellValue(spQualifications.getSignAgency());
            row.createCell(5).setCellValue(expirationDateStr);
            row.createCell(6).setCellValue(formattedDate2);
            row.createCell(7).setCellValue(spQualifications.getRemarks());
            row.createCell(8).setCellValue(spQualifications.getCreateBy());
            String formattedDate3 = spQualifications.getCreateDate().toInstant()
                    .atZone(ZoneId.systemDefault())
                    .toLocalDateTime()
                    .format(formatter2);
            row.createCell(9).setCellValue(formattedDate3);
        }

        try (FileOutputStream outputStream = new FileOutputStream(filePath)) {
            workbook.write(outputStream);
        }

        workbook.close();
    }

    private void zipDirectory(File directory, ZipOutputStream zos, String path) throws IOException {
        File[] files = directory.listFiles();
        byte[] buffer = new byte[1024];

        for (File file : files) {
            if (file.isDirectory()) {
                zipDirectory(file, zos, path + file.getName() + "/");
            } else {
                FileInputStream fis = new FileInputStream(file);
                ZipEntry zipEntry = new ZipEntry(path + file.getName());
                zos.putNextEntry(zipEntry);

                int length;
                while ((length = fis.read(buffer)) > 0) {
                    zos.write(buffer, 0, length);
                }

                fis.close();
                zos.closeEntry();
            }
        }
    }

    public void zipFile(String fileName) throws IOException {
        // 获取当前目录路径
        String currentDirectory = System.getProperty("user.dir");

        // 创建压缩包文件
        String zipFileName = fileName.substring(0, fileName.lastIndexOf('.')) + ".zip";

        try (FileOutputStream fos = new FileOutputStream(zipFileName);
             ZipOutputStream zos = new ZipOutputStream(fos)) {
            zipFile(new File(currentDirectory + "/" + fileName), "", zos);
        }
    }

    private void zipFile(File fileToZip, String parentPath, ZipOutputStream zos) throws IOException {
        if (fileToZip.isDirectory()) {
            String entryName = parentPath + fileToZip.getName() + "/";
            zos.putNextEntry(new ZipEntry(entryName));
            zos.closeEntry();

            File[] children = fileToZip.listFiles();
            for (File childFile : children) {
                zipFile(childFile, entryName, zos);
            }
        } else {
            FileInputStream fis = new FileInputStream(fileToZip);

            String entryName = parentPath + fileToZip.getName();
            zos.putNextEntry(new ZipEntry(entryName));

            byte[] buffer = new byte[1024];
            int length;
            while ((length = fis.read(buffer)) >= 0) {
                zos.write(buffer, 0, length);
            }

            fis.close();
            zos.closeEntry();
        }
    }

    public static void deleteFolder(String folderName) {
        File folder = new File(folderName);
        deleteFolder(folder);
    }

    private static void deleteFolder(File folder) {
        if (folder.exists() && folder.isDirectory()) {
            File[] files = folder.listFiles();
            if (files != null) {
                for (File file : files) {
                    if (file.isDirectory()) {
                        deleteFolder(file);
                    } else {
                        file.delete();
                    }
                }
            }
            folder.delete();
            System.out.println("文件成功删除");
        } else {
            System.out.println("Folder does not exist or is not a directory.");
        }
    }
}
